From e063a0fdf13a09ca44588862d6b0b4f04232759f Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 8 Nov 2012 15:26:33 +0100 Subject: [PATCH] symboliccolor: Split out HSLA code --- gtk/Makefile.am | 2 + gtk/gtkhsla.c | 185 +++++++++++++++++++++++++++++++++++++++++ gtk/gtkhslaprivate.h | 47 +++++++++++ gtk/gtksymboliccolor.c | 173 ++------------------------------------ 4 files changed, 242 insertions(+), 165 deletions(-) create mode 100644 gtk/gtkhsla.c create mode 100644 gtk/gtkhslaprivate.h diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 7e9ebffea3..ca7dbaaa5c 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -478,6 +478,7 @@ gtk_private_h_sources = \ gtkfontchooserprivate.h \ gtkfontchooserutils.h \ gtkgradientprivate.h \ + gtkhslaprivate.h \ gtkiconcache.h \ gtkiconhelperprivate.h \ gtkiconviewprivate.h \ @@ -719,6 +720,7 @@ gtk_base_c_sources = \ gtkframe.c \ gtkgradient.c \ gtkgrid.c \ + gtkhsla.c \ gtkiconcache.c \ gtkiconcachevalidator.c \ gtkiconfactory.c \ diff --git a/gtk/gtkhsla.c b/gtk/gtkhsla.c new file mode 100644 index 0000000000..a78849789d --- /dev/null +++ b/gtk/gtkhsla.c @@ -0,0 +1,185 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2012 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gtkhslaprivate.h" + +#include + +void +_gtk_hsla_init (GtkHSLA *hsla, + double hue, + double saturation, + double lightness, + double alpha) +{ + g_return_if_fail (hsla != NULL); + + if (hue >= 0) + hsla->hue = fmod (hue, 360); + else + hsla->hue = fmod (hue, 360) + 360; + hsla->saturation = CLAMP (saturation, 0, 1); + hsla->lightness = CLAMP (lightness, 0, 1); + hsla->alpha = CLAMP (alpha, 0, 1); +} + +void +_gtk_hsla_init_from_rgba (GtkHSLA *hsla, + const GdkRGBA *rgba) +{ + gdouble min; + gdouble max; + gdouble red; + gdouble green; + gdouble blue; + gdouble delta; + + g_return_if_fail (hsla != NULL); + g_return_if_fail (rgba != NULL); + + red = rgba->red; + green = rgba->green; + blue = rgba->blue; + + if (red > green) + { + if (red > blue) + max = red; + else + max = blue; + + if (green < blue) + min = green; + else + min = blue; + } + else + { + if (green > blue) + max = green; + else + max = blue; + + if (red < blue) + min = red; + else + min = blue; + } + + hsla->lightness = (max + min) / 2; + hsla->saturation = 0; + hsla->hue = 0; + hsla->alpha = rgba->alpha; + + if (max != min) + { + if (hsla->lightness <= 0.5) + hsla->saturation = (max - min) / (max + min); + else + hsla->saturation = (max - min) / (2 - max - min); + + delta = max -min; + if (red == max) + hsla->hue = (green - blue) / delta; + else if (green == max) + hsla->hue = 2 + (blue - red) / delta; + else if (blue == max) + hsla->hue = 4 + (red - green) / delta; + + hsla->hue *= 60; + if (hsla->hue < 0.0) + hsla->hue += 360; + } +} + +void +_gdk_rgba_init_from_hsla (GdkRGBA *rgba, + const GtkHSLA *hsla) +{ + gdouble hue; + gdouble lightness; + gdouble saturation; + gdouble m1, m2; + + lightness = hsla->lightness; + saturation = hsla->saturation; + + if (lightness <= 0.5) + m2 = lightness * (1 + saturation); + else + m2 = lightness + saturation - lightness * saturation; + m1 = 2 * lightness - m2; + + rgba->alpha = hsla->alpha; + + if (saturation == 0) + { + rgba->red = lightness; + rgba->green = lightness; + rgba->blue = lightness; + } + else + { + hue = hsla->hue + 120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + rgba->red = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + rgba->red = m2; + else if (hue < 240) + rgba->red = m1 + (m2 - m1) * (240 - hue) / 60; + else + rgba->red = m1; + + hue = hsla->hue; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + rgba->green = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + rgba->green = m2; + else if (hue < 240) + rgba->green = m1 + (m2 - m1) * (240 - hue) / 60; + else + rgba->green = m1; + + hue = hsla->hue - 120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + rgba->blue = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + rgba->blue = m2; + else if (hue < 240) + rgba->blue = m1 + (m2 - m1) * (240 - hue) / 60; + else + rgba->blue = m1; + } +} + diff --git a/gtk/gtkhslaprivate.h b/gtk/gtkhslaprivate.h new file mode 100644 index 0000000000..3cc97d9b71 --- /dev/null +++ b/gtk/gtkhslaprivate.h @@ -0,0 +1,47 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2012 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __GTK_HSLA_PRIVATE_H__ +#define __GTK_HSLA_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GtkHSLA GtkHSLA; + +struct _GtkHSLA { + double hue; + double saturation; + double lightness; + double alpha; +}; + +void _gtk_hsla_init (GtkHSLA *hsla, + double hue, + double saturation, + double lightness, + double alpha); +void _gtk_hsla_init_from_rgba (GtkHSLA *hsla, + const GdkRGBA *rgba); +/* Yes, I can name that function like this! */ +void _gdk_rgba_init_from_hsla (GdkRGBA *rgba, + const GtkHSLA *hsla); + +G_END_DECLS + +#endif /* __GTK_HSLA_PRIVATE_H__ */ diff --git a/gtk/gtksymboliccolor.c b/gtk/gtksymboliccolor.c index 658a14cb02..8f312cf425 100644 --- a/gtk/gtksymboliccolor.c +++ b/gtk/gtksymboliccolor.c @@ -18,6 +18,7 @@ #include "config.h" #include "gtkcssrgbavalueprivate.h" #include "gtkcssstylepropertyprivate.h" +#include "gtkhslaprivate.h" #include "gtkstylepropertyprivate.h" #include "gtksymboliccolorprivate.h" #include "gtkstyleproperties.h" @@ -509,179 +510,21 @@ gtk_symbolic_color_unref (GtkSymbolicColor *color) _gtk_css_value_unref ((GtkCssValue *) color); } -static void -rgb_to_hls (gdouble *r, - gdouble *g, - gdouble *b) -{ - gdouble min; - gdouble max; - gdouble red; - gdouble green; - gdouble blue; - gdouble h, l, s; - gdouble delta; - - red = *r; - green = *g; - blue = *b; - - if (red > green) - { - if (red > blue) - max = red; - else - max = blue; - - if (green < blue) - min = green; - else - min = blue; - } - else - { - if (green > blue) - max = green; - else - max = blue; - - if (red < blue) - min = red; - else - min = blue; - } - - l = (max + min) / 2; - s = 0; - h = 0; - - if (max != min) - { - if (l <= 0.5) - s = (max - min) / (max + min); - else - s = (max - min) / (2 - max - min); - - delta = max -min; - if (red == max) - h = (green - blue) / delta; - else if (green == max) - h = 2 + (blue - red) / delta; - else if (blue == max) - h = 4 + (red - green) / delta; - - h *= 60; - if (h < 0.0) - h += 360; - } - - *r = h; - *g = l; - *b = s; -} - -static void -hls_to_rgb (gdouble *h, - gdouble *l, - gdouble *s) -{ - gdouble hue; - gdouble lightness; - gdouble saturation; - gdouble m1, m2; - gdouble r, g, b; - - lightness = *l; - saturation = *s; - - if (lightness <= 0.5) - m2 = lightness * (1 + saturation); - else - m2 = lightness + saturation - lightness * saturation; - m1 = 2 * lightness - m2; - - if (saturation == 0) - { - *h = lightness; - *l = lightness; - *s = lightness; - } - else - { - hue = *h + 120; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - r = m1 + (m2 - m1) * hue / 60; - else if (hue < 180) - r = m2; - else if (hue < 240) - r = m1 + (m2 - m1) * (240 - hue) / 60; - else - r = m1; - - hue = *h; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - g = m1 + (m2 - m1) * hue / 60; - else if (hue < 180) - g = m2; - else if (hue < 240) - g = m1 + (m2 - m1) * (240 - hue) / 60; - else - g = m1; - - hue = *h - 120; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - b = m1 + (m2 - m1) * hue / 60; - else if (hue < 180) - b = m2; - else if (hue < 240) - b = m1 + (m2 - m1) * (240 - hue) / 60; - else - b = m1; - - *h = r; - *l = g; - *s = b; - } -} - static void _shade_color (GdkRGBA *color, gdouble factor) { - GdkRGBA temp; + GtkHSLA hsla; - temp = *color; - rgb_to_hls (&temp.red, &temp.green, &temp.blue); + _gtk_hsla_init_from_rgba (&hsla, color); - temp.green *= factor; - if (temp.green > 1.0) - temp.green = 1.0; - else if (temp.green < 0.0) - temp.green = 0.0; + hsla.lightness *= factor; + hsla.lightness = CLAMP (hsla.lightness, 0.0, 1.0); - temp.blue *= factor; - if (temp.blue > 1.0) - temp.blue = 1.0; - else if (temp.blue < 0.0) - temp.blue = 0.0; + hsla.hue *= factor; + hsla.hue = CLAMP (hsla.hue, 0.0, 1.0); - hls_to_rgb (&temp.red, &temp.green, &temp.blue); - *color = temp; + _gdk_rgba_init_from_hsla (color, &hsla); } /** -- 2.30.2